
package code.codeworld.space.blog.service.impl;

import code.codeworld.common.kits.EditTextUtil;
import code.codeworld.space.blog.mapper.BlogJPA;
import code.codeworld.space.blog.mapper.BlogMapper;
import code.codeworld.space.blog.model.Blog;
import code.codeworld.space.blog.model.vo.BlogVo;
import code.codeworld.space.blog.service.BlogService;
import code.codeworld.common.kits.PageUtil;
import code.codeworld.common.kits.Result;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * blogService接口实现类
 *
 * @author freecode
 * @date 2023/03/23 00:20
 **/
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService {
    @Resource
    private BlogJPA blogJPA;
    @Resource
    private BlogMapper blogMapper;
    Lock lock = new ReentrantLock();

    @Override
    public Result<String> add(Blog blog) {
        Result<String> checkParam = checkParam(blog);
        if (!checkParam.isFinish()) {
            return checkParam;
        }
        //Consumer<Object> consumer = s -> blogJPA.save(blog);
        //consumer.accept(blog);
        //return Result.tryCatch(consumer, blog);
        try {
            blogJPA.save(blog);
            return Result.ok();
            //boolean add = super.save(blog);
            /*if (add) {
                return Result.ok();
            } else {
                return Result.error();
            }*/
        } catch (Exception e) {
            return Result.exception(e.getMessage());
        }
    }

    @Override
    public Page<Blog> page(BlogVo blogVo) {
        Integer pageNum = blogVo.getPageNum();
        Integer pageSize = blogVo.getPageSize();
        if (pageNum == null || pageNum <= BigDecimal.ROUND_DOWN) {
            pageNum = BigInteger.ZERO.intValue();
        } else {
            pageNum = pageNum - BigDecimal.ROUND_DOWN;
        }
        if (pageSize == null) {
            pageSize = BigInteger.TEN.intValue();
        }
        List<Sort.Order> orderList = new ArrayList<>();
        if (StringUtils.hasText(blogVo.getPageOrders())) {
            String[] orders = blogVo.getPageOrders().split(";");
            for (String order : orders) {
                String[] item = order.split(",");
                orderList.add(new Sort.Order(item[0].equals("desc") ? Sort.Direction.DESC : Sort.Direction.ASC, item[1]));
            }
        }
        blogVo.setPageable(PageRequest.of(pageNum, pageSize, Sort.by(orderList)));
        Page<Blog> page = blogJPA.findAll(blogVo.getPageable());
        if (!page.isEmpty()) {
            //补充排序--sql执行多个字段排序时有时未生效后面的（数据limit、）
            if (orderList.size() > BigDecimal.ROUND_DOWN) {
                for (int i = 1; i < orderList.size(); i++) {
                    if (orderList.get(i).getProperty().equals("create_time")) {
                        if (orderList.get(i).isDescending()) {
                            page.getContent().stream().sorted(Comparator.comparing(Blog::getCreateTime).reversed()).collect(Collectors.toList());
                        } else {
                            page.getContent().stream().sorted(Comparator.comparing(Blog::getCreateTime)).collect(Collectors.toList());
                        }
                    }
                    if (orderList.get(i).getProperty().equals("star_num")) {
                        if (orderList.get(i).isDescending()) {
                            page.getContent().stream().sorted(Comparator.comparing(Blog::getStarNum).reversed()).collect(Collectors.toList());
                        } else {
                            page.getContent().stream().sorted(Comparator.comparing(Blog::getStarNum)).collect(Collectors.toList());
                        }
                    }
                    if (orderList.get(i).getProperty().equals("wordage")) {
                        if (orderList.get(i).isDescending()) {
                            page.getContent().stream().sorted(Comparator.comparing(Blog::getWordage).reversed()).collect(Collectors.toList());
                        } else {
                            page.getContent().stream().sorted(Comparator.comparing(Blog::getWordage)).collect(Collectors.toList());
                        }
                    }
                }
            }
            int autoNum = pageNum * pageSize;
            for (Blog t : page.getContent()) {
                //序号自增
                t.setAutoNum(++autoNum);
                //简介过滤html符号
                t.setBlurb(EditTextUtil.getText(t.getBlurb()));
            }
        }
        return page;
    }

    @Override
    public com.baomidou.mybatisplus.extension.plugins.pagination.Page<Blog> myPage(BlogVo blogVo) {
        Integer[] pageLimits = new Integer[]{blogVo.getPageNum(), blogVo.getPageSize()};
        PageUtil.getPageLimits(pageLimits);
        blogVo.setPageNum(pageLimits[0]);
        blogVo.setPageSize(pageLimits[1]);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<Blog> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<Blog>();
        List<Sort.Order> orderList = new ArrayList<>();
        if (StringUtils.hasText(blogVo.getPageOrders())) {
            String[] orders = blogVo.getPageOrders().split(";");
            for (String order : orders) {
                String[] item = order.split(",");
                orderList.add(new Sort.Order(item[0].equals("desc") ? Sort.Direction.DESC : Sort.Direction.ASC, item[1]));
            }
            blogVo.setSortField(orderList.get(0).getProperty());
            blogVo.setSortOrder(orderList.get(0).getDirection().name());
        }
        int count = blogMapper.findByKeywordCount(blogVo);
        if (count > BigDecimal.ROUND_UP) {
            List<Blog> data = blogMapper.findByKeyword(blogVo);
            //补充排序--sql执行多个字段排序时有时未生效后面的（数据limit、）
            if (orderList.size() > BigDecimal.ROUND_DOWN) {
                for (int i = 1; i < orderList.size(); i++) {
                    if (orderList.get(i).getProperty().equals("createTime")) {
                        if (orderList.get(i).isDescending()) {
                            data.stream().sorted(Comparator.comparing(Blog::getCreateTime).reversed()).collect(Collectors.toList());
                        } else {
                            data.stream().sorted(Comparator.comparing(Blog::getCreateTime)).collect(Collectors.toList());
                        }
                    }
                    if (orderList.get(i).getProperty().equals("starNum")) {
                        if (orderList.get(i).isDescending()) {
                            data.stream().sorted(Comparator.comparing(Blog::getStarNum).reversed()).collect(Collectors.toList());
                        } else {
                            data.stream().sorted(Comparator.comparing(Blog::getStarNum)).collect(Collectors.toList());
                        }
                    }
                    if (orderList.get(i).getProperty().equals("wordage")) {
                        if (orderList.get(i).isDescending()) {
                            data.stream().sorted(Comparator.comparing(Blog::getWordage).reversed()).collect(Collectors.toList());
                        } else {
                            data.stream().sorted(Comparator.comparing(Blog::getWordage)).collect(Collectors.toList());
                        }
                    }
                }
            }
            int autoNum = pageLimits[0];
            for (Blog t : data) {
                //序号自增
                t.setAutoNum(++autoNum);
                //过滤html符号
                t.setBlurb(EditTextUtil.getText(t.getBlurb()));
            }
            page.setRecords(data);
        }
        page.setTotal(count);
        return page;
    }

    @Override
    public Blog detail(Blog blog) {
        return this.queryEntity(blog.getId());
    }

    @Override
    public Blog queryEntity(Integer id) {
        return blogJPA.getReferenceById(id);
    }

    @Override
    public List<Blog> queryEntityList(Blog blog) {
        Example<Blog> example = Example.of(blog);
        return blogJPA.findAll(example);
    }

    @Override
    public Result<String> checkParam(Blog blog) {
        Blog checkParam = new Blog();
        checkParam.setTitle(blog.getTitle());
        Example<Blog> example = Example.of(checkParam);
        Optional<Blog> dbData = blogJPA.findOne(example);
        if (dbData.isPresent()) {
            return Result.error("标题重复");
        }
        return Result.ok();
    }

    @Override
    public Result<String> edit(Blog blog) {
        Blog checkParam = new Blog();
        checkParam.setTitle(blog.getTitle());
        List<Blog> dbData = queryEntityList(checkParam);
        if (!dbData.isEmpty()) {
            return Result.error("标题重复");
        }
        try {
            blogJPA.save(blog);
            return Result.ok();
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    @Override
    public Result<String> editMark(BlogVo blogVo) {
        Blog dbData = this.queryEntity(blogVo.getId());
        if (blogVo.getStarNum() != null) {
            dbData.setStarNum(dbData.getStarNum() + blogVo.getStarNum());
        }
        if (blogVo.getCollectNum() != null) {
            dbData.setCollectNum(dbData.getCollectNum() + blogVo.getCollectNum());
        }
        if (!StringUtils.isEmpty(blogVo.getComment())) {
            dbData.setComment(dbData.getComment() + "\\\\" + blogVo.getComment());
        }
        lock.lock();
        try {
            blogJPA.save(dbData);
            lock.unlock();
            return Result.ok();
        } catch (Exception e) {
            lock.unlock();
            return Result.error(e.getMessage());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<String> delete(Blog blog) {
        if (blog.getDeleteFlag() == null) {
            // 执行删除
            try {
                blogJPA.deleteById(blog.getId());
                //personalLogJPA.deleteAll(personalLogList);
                return Result.ok();
            } catch (Exception e) {
                return Result.error(e.getMessage());
            }
        } else {
            // 执行隐藏
            try {
                blogJPA.save(blog);
                return Result.ok();
                // boolean update = super.updateById(blog);
                /*LambdaUpdateWrapper<blog> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(blog::getId, blog.getId())
                        .set(blog::getDeleteFlag, blog.getDeleteFlag())
                        .set(blog::getStates, blog.getStates());
                boolean update = super.update(null, updateWrapper);*/
                /*if (update) {
                    return Result.ok();
                } else {
                    return Result.error();
                }*/
            } catch (Exception e) {
                return Result.error(e.getMessage());
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<String> deleteList(List<Blog> blogList) {
        if (blogList.get(0).getDeleteFlag() == null) {
            // 执行删除
            Iterable<Integer> ids = blogList.stream().map(Blog::getId).collect(Collectors.toList());
            try {
                blogJPA.deleteAllByIdInBatch(Collections.singleton(ids));
                //personalLogJPA.deleteAll(personalLogList);
                return Result.ok();
            } catch (Exception e) {
                return Result.error(e.getMessage());
            }
        } else {
            // 执行隐藏
            try {
                //blogJPA.saveAll(blogList);
                boolean update = super.updateBatchById(blogList);
                if (update) {
                    return Result.ok();
                } else {
                    return Result.error();
                }
            } catch (Exception e) {
                return Result.error(e.getMessage());
            }
        }
    }


}
